package com.example.statemachine.controller;

import com.example.statemachine.core.StateEnum;
import com.example.statemachine.entity.StateTransitionLog;
import com.example.statemachine.entity.Task;
import com.example.statemachine.service.TaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/api/tasks")
@RequiredArgsConstructor
public class TaskController {

    private final TaskService taskService;

    @PersistenceContext
    private EntityManager entityManager;

    @PostMapping("/{taskId}/start")
    public Task startProcess(@PathVariable Long taskId,
                             @RequestParam String operator,
                             @RequestParam String assignee) {
        return taskService.startProcess(taskId, operator, assignee);
    }

    @PostMapping("/{taskId}/submit-approval")
    public Task submitApproval(@PathVariable Long taskId,
                               @RequestParam String operator,
                               @RequestParam String approver) {
        return taskService.submitApproval(taskId, operator, approver);
    }

    @PutMapping("/{taskId}/modify")
    public Task modifyTask(@PathVariable Long taskId,
                           @RequestParam String operator,
                           @RequestParam(required = false) String assignee,
                           @RequestParam(required = false) String description) {
        return taskService.modifyTask(taskId, operator, assignee, description);
    }

    @GetMapping("/execute-test")
    @Transactional
    public String executeTest() {
        log.info("开始状态机测试...");

        // 创建测试任务
        Task task = new Task();
        task.setTaskNo("TASK002");
        task.setStatus(StateEnum.INIT);
        task.setDescription("测试任务");
        entityManager.persist(task);
        entityManager.flush();

        Long taskId = task.getId();
        log.info("创建任务: ID={}, TaskNo={}, Status={}", taskId, task.getTaskNo(), task.getStatus());

        try {
            // 测试状态流转
            log.info("开始处理任务...");
            Task result = taskService.startProcess(taskId, "user1", "assignee1");

            log.info("开始处理后状态: {}, 处理人: {}", result.getStatus(), result.getAssignee());

            // 验证日志记录
            verifyTransitionLog(task.getTaskNo(), StateEnum.INIT, StateEnum.PROCESSING, "user1");

            log.info("修改任务信息...");
            result = taskService.modifyTask(taskId, "user1", "assignee2", "更新描述信息");

            log.info("修改后状态: {}, 处理人: {}", result.getStatus(), result.getAssignee());

            log.info("提交审批...");
            result = taskService.submitApproval(taskId, "user1", "approver1");

            log.info("提交审批后状态: {}, 审批人: {}", result.getStatus(), result.getApprover());

            log.info("审批通过...");
            result = taskService.approveTask(taskId, "approver1");
            log.info("审批通过后状态: {}", result.getStatus());

            log.info("状态机测试完成!");

            return "SUCCESS";
        } catch (Exception e) {
            log.error("状态机测试失败", e);
            throw e;
        }
    }


    private void verifyTransitionLog(String businessId, StateEnum fromState, StateEnum toState, String operator) {
        TypedQuery<StateTransitionLog> query = entityManager.createQuery(
                "SELECT l FROM StateTransitionLog l WHERE l.businessId = :businessId ORDER BY l.operateTime DESC",
                StateTransitionLog.class);
        query.setParameter("businessId", businessId);
        query.setMaxResults(1);

        List<StateTransitionLog> logs = query.getResultList();

        StateTransitionLog latestLog = logs.get(0);

        log.info("验证状态转换日志: {} -> {} -> {}",
                latestLog.getFromState(), latestLog.getToState(), latestLog.getEvent());
    }
}